
/**
 * Created by jiangqifan on 16/3/28.
 */


 "use strict";
var Bucket = require('./bucket');
var _ = require('lodash');

class Node{
  constructor(name){
    this._document = null;
    this._parent = null;
    this._readOnly = false;
    this._name = name;
    this._text = null;
  }
  getParent(){
    return this._parent;
  }
  setParent(element){
    this._parent = element;
  }
  setDocument(doc){
    this._document = doc;
  }
  getDocument(){
    return this._document;
  }
  isReadOnly(){
    return this.readOnly;
  }
  hasContent(){
    return false;
  }
  getName(){
    return this._name;
  }
  setName(name){
    this.name = name;
  }
  getText(){
    return this._text;
  }
  setText(text){
    this._text = text;
  }
  asXML(){
    return '';
  }

}

class Document extends Node{

  constructor(){
    super();
    this._root = null;
    this._encoding = 'UTF-8';
  }

  getRootElement(){
    return this._root;
  }
  setRootElement(element){
    this._root = element;
  }
  setXMLEncoding(encoding){
    this._encoding = encoding;
  }
  getXMLEncoding(){
    return this._encoding;
  }
  addElement(name){
    this._root = new Element(null, name);
    this._root.setDocument(this);
    this._root.setIsRootDocument(true);
    return this._root;
  }
  asXML(){
    var result = "";//"<?xml version='1.0' encoding='"+this.getXMLEncoding()+"'?>";
    if(this._root){
      result += this._root.asXML();
    }
    return result;
  }
}

class Element extends Node{
  constructor(parent, name){
    super(name);
    this._attributes = new Bucket();
    this._cdata = null;
    this._children = []; //node
    this._isRootElement = false;
  }
  addAttribute(name, value){
    if(null != name){
      this._attributes.add(name, new Attribute(name, value));
    }
  }
  addCDATA(cdata){
    this._cdata = cadata;
  }
  getText(){
    return this._text;
  }
  getTextTrim(){
    return this._text?this._text.trim():'';
  }
  attributes(){
    return this._attributes;
  }
  attribute(name){
    return this._attributes.get(name);
  }
  attributeValue(name){
    if(this._attributes.contains(name)){
      return this._attributes.get(name).getValue();
    }
  }
  element(name){
    return _.find(this._children, function(ele){
      return ele.getName() == name;
    });
  }
  elements(name){
    return _.filter(this._children, function(ele){
      return ele.getName() == name;
    });
  }
  addElement(name){
    let element = new Element(this, name);
    element.setDocument(this.getDocument());
    this._children.push(element);
    return element;
  }
  isRootElement(){
    return this._isRootElement;
  }
  setIsRootDocument(value){
    this._isRootElement = value;
  }
  isTextOnly(){
    return 0 == this.children.length && {} == this._attributes.size() == 0;
  }
  elementText(name){
    var theEle =  _.find(this._children, function(ele){
      return ele.getName() == name;
    });
    if(theEle){
      return theEle.getText();
    }
  }
  elementTextTrim(name){
    var theEle =  _.find(this._children, function(ele){
      return ele.getName() == name;
    });
    if(theEle){
      return theEle.getTextTrim();
    }
  }
  asXML(){
    let name = this.getName();
    var result = '<'+name;

    var attributeArray = this._attributes.toArray();
    _.forEach(attributeArray, function(attribute){
      result += ' ' + attribute.asXML();
    });
    result += '>';
    if(this._children.length > 0){
      _.forEach(this._children, function(child){
        result += child.asXML();
      });
    } else {
      if(null != this.getText()){
        result += this.getText();
      }
    }

    result += '</'+name+'>';
    return result;
  }
}


class Attribute{
  constructor(name,value){
    this._name = name;
    this._value = value;
  }
  getName(){
    return this._name;
  }
  setName(name){
    this._name = name;
  }
  getValue(){
    return this._value;
  }
  setValue(){
    return this._value;
  }
  asXML(){
    return this._name + "='"+ this._value+"'";
  }
}


exports.Node = Node;
exports.Document =  Document;
